package net.esj.auth.pojo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import net.esj.basic.pojo.AbstractPojo;
import net.esj.basic.pojo.op.Administrator;
import net.esj.basic.pojo.op.Operation;
import net.esj.basic.pojo.op.OperationSet;
import net.esj.basic.pojo.op.Operator;

import org.apache.commons.lang.StringUtils;


public class CoreAdmin extends AbstractPojo<String> implements Operator,Administrator{

	public static enum ADMIN_STATE{
		NORMAL(1),FREEZE(0);
		
		private int key;

		private ADMIN_STATE(int key) {
			this.key = key;
		}

		public int getKey() {
			return key;
		}
		
		public ADMIN_STATE valueOf(int key){
			for(ADMIN_STATE ad : values()){
				if(ad.getKey() == key){
					return ad;
				}
			}
			return null;
		}
	}
	
	public static final String MOBJECT_TYPE = "CORE_ADMIN";
	
	private String id;
	private String name;
	private String subName;
	private String password;
	private Date gmtCreate;
	private Date gmtModify;
	private Date lastLoginTime;
	private String lastLoginIp;
	private int state;
	private int is_delete;
	private String phone;
	private String address;
	private String creatorId;
	private String creatorName;



	private Set<CoreAuthGroup> groups = new HashSet<CoreAuthGroup>(0);
	private Set<CoreAuthFunc> functions = new HashSet<CoreAuthFunc>(0);
	
	private List<CoreAuthFunc> allowedFunctions = Collections.EMPTY_LIST;
	
	private List<CoreAuthFunc> allowedTree = Collections.EMPTY_LIST;
	
	public static final String SUPER_ADMINISTRATOR_NAME = "AdminiStratoR";
	
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public int getIs_delete() {
		return is_delete;
	}

	public void setIs_delete(int is_delete) {
		this.is_delete = is_delete;
	}
	@Override
	public String getId() {
		return id;
	}

	@Override
	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	public String getSubName() {
		return subName;
	}

	public void setSubName(String subName) {
		this.subName = subName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getGmtCreate() {
		return gmtCreate;
	}

	public void setGmtCreate(Date gmtCreate) {
		this.gmtCreate = gmtCreate;
	}

	public Date getGmtModify() {
		return gmtModify;
	}

	public void setGmtModify(Date gmtModify) {
		this.gmtModify = gmtModify;
	}

	public Date getLastLoginTime() {
		return lastLoginTime;
	}

	public void setLastLoginTime(Date lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}

	public String getLastLoginIp() {
		return lastLoginIp;
	}

	public void setLastLoginIp(String lastLoginIp) {
		this.lastLoginIp = lastLoginIp;
	}

	public Set<CoreAuthGroup> getGroups() {
		return groups;
	}

	public void setGroups(Set<CoreAuthGroup> groups) {
		this.groups = groups;
	}

	public Set<CoreAuthFunc> getFunctions() {
		return functions;
	}

	public void setFunctions(Set<CoreAuthFunc> functions) {
		this.functions = functions;
	}

	public String getCreatorId() {
		return creatorId;
	}

	public void setCreatorId(String creatorId) {
		this.creatorId = creatorId;
	}

	public String getCreatorName() {
		return creatorName;
	}

	public void setCreatorName(String creatorName) {
		this.creatorName = creatorName;
	}
	public List<CoreAuthFunc> getAllowedFunctions() {
		if(allowedFunctions == Collections.EMPTY_LIST){
			Set<CoreAuthFunc> tempFuncs = new HashSet<CoreAuthFunc>();//必须先要用set过滤重复项
			for(CoreAuthGroup group: getGroups()){
				tempFuncs.addAll(group.getFunctions());
			}
			for(CoreAuthFunc f:getFunctions()){
				appendAllowedFuncs(tempFuncs, f);
			}
			tempFuncs.addAll(getFunctions());
			allowedFunctions = new ArrayList<CoreAuthFunc>(tempFuncs);
			Collections.sort(allowedFunctions, new Comparator<CoreAuthFunc>() {

				@Override
				public int compare(CoreAuthFunc o1, CoreAuthFunc o2) {
					return o1.getSort() - o2.getSort();
				}
			});
		}
		return allowedFunctions;
	}
	
	private void appendAllowedFuncs(Set<CoreAuthFunc> set,CoreAuthFunc func){
		set.add(func);
		for(CoreAuthFunc f : func.getChildren()){
			appendAllowedFuncs(set, f);
		}
	}
	
	public boolean isAllowed(String uri,Map requestParams){
		for(CoreAuthFunc func: getAllowedTree()){
			if(isAllowed(uri, requestParams, func)){
				return true;
			}
			/*if(Pattern.matches(func.getAnalyzedUrl(), uri)
					&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
				return true;
			}
			for(Map.Entry<String, Map<String,String[]>> entry: func.getRights().entrySet()){
				if(Pattern.matches(entry.getKey(), uri)
						&& CoreAuthFunc.checkParams(entry.getValue(), requestParams)){
					return true;
				}
			}*/
		}
		return false;
	}
	
	protected boolean isAllowed(String uri,Map requestParams,CoreAuthFunc func){
		if(Pattern.matches(func.getAnalyzedUrl(), uri)
				&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
			return true;
		}
		for(Map.Entry<String, Map<String,String[]>> entry: func.getRights().entrySet()){
			if(Pattern.matches(entry.getKey(), uri)
					&& CoreAuthFunc.checkParams(entry.getValue(), requestParams)){
				return true;
			}
		}
		for(CoreAuthFunc child : func.getChildren()){
			if(isAllowed(uri, requestParams,child)){
				return true;
			}
		}
		return false;
	}
	
	public List<CoreAuthFunc> getAllowedTree() {
		if(allowedTree == Collections.EMPTY_LIST){
			allowedTree = new ArrayList<CoreAuthFunc>();
			for(CoreAuthFunc func : getAllowedFunctions()){
				if(func.getParent()==null){//根目录
					allowedTree.add(func);
					setChild(func, getAllowedFunctions());
				}
			}
		}
		return allowedTree;
	}

	private void setChild(CoreAuthFunc parent ,List<CoreAuthFunc> list){
		for(CoreAuthFunc bm : list){
			if(bm.getParent()!=null &&  StringUtils.equals(bm.getParent().getId(), parent.getId())){
				parent.getChildren().add(bm);
				setChild(bm, list);
			}
		}
	}
	
	public String loggerAllGroup(){
		StringBuilder sb = new StringBuilder();
		for(CoreAuthGroup group: groups){
			sb.append(group.getName()).append(",");
		}
		return sb.toString();
	}
	
	public String loggerAllFunc(){
		StringBuilder sb = new StringBuilder();
		for(CoreAuthFunc func: functions){
			sb.append(func.getName()).append(",");
		}
		return sb.toString();
	}

	@Override
	public String getMType() {
		return MOBJECT_TYPE;
	}

	@Override
	public boolean isSuper() {
		return false;
	}

	@Override
	public Collection<CoreAuthFunc> authFunctions() {
		return getAllowedTree();
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	@Override
	public OperationSet findOperations(String uri, Map requestParams) {
		OperationSet set = new OperationSet();
		findOperations(uri, requestParams,set,getAllowedTree());
		/*for(CoreAuthFunc func: getAllowedFunctions()){
			if(Pattern.matches(func.getAnalyzedUrl(), uri)
					&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
				if(func.getIsOper()){
					Operation op = new Operation();
					op.setBody(func.getDefine());
					op.setIcon(func.getIcon());
					op.setTarget(func.getScope());
					op.setTitle(func.getName());
					op.setSort(func.getSort());
					op.setMenu(func.getIsMenu());
					op.setCheck(func.getDefineCheck());
					set.push(op);
				}
			}
		}*/
		return set;
	}
	
	public void findOperations(String uri, Map requestParams,OperationSet set,Collection<CoreAuthFunc> funcs){
		for(CoreAuthFunc func:funcs){
			if(Pattern.matches(func.getAnalyzedUrl(), uri)&& CoreAuthFunc.checkParams(func.getParams(), requestParams)){
				if(func.getIsOper()){
					Operation op = new Operation();
					op.setBody(func.getDefine());
					op.setIcon(func.getIcon());
					op.setTarget(func.getScope());
					op.setTitle(func.getName());
					op.setSort(func.getSort());
					op.setMenu(func.getIsMenu());
					op.setCheck(func.getDefineCheck());
					set.push(op);
					if(op.isMenu()){
						resolveOperationChildren(func, op);
					}
				}else{
					findOperations(uri, requestParams, set, func.getChildren());
				}
			}else{
				findOperations(uri, requestParams, set, func.getChildren());
			}
		}
	}
	
	private void resolveOperationChildren(CoreAuthFunc func,Operation parentOp){
		for(CoreAuthFunc f : func.getChildren()){
			if(f.getIsOper()){
				Operation op = new Operation();
				op.setBody(f.getDefine());
				op.setIcon(f.getIcon());
				op.setTarget(f.getScope());
				op.setTitle(f.getName());
				op.setMenu(f.getIsMenu());
				parentOp.addChild(op);
				resolveOperationChildren(f, op);
			}
		}
	}
}
